package com.eastfair.pay.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.eastfair.common.dto.Collect;
import com.eastfair.common.dto.JYApplyInvoiceInfoDTO;
import com.eastfair.common.dto.JYApplyInvoiceMxDTO;
import com.eastfair.common.dto.JYApplyRefundDTO;
import com.eastfair.common.dto.JYApplyRefundMxDTO;
import com.eastfair.common.dto.JYPaymentCollectRecordDTO;
import com.eastfair.common.dto.JYTransactionOrderDTO;
import com.eastfair.common.dto.OrderPaymentPlan;
import com.eastfair.common.req.JYReq;
import com.eastfair.core.exception.BizException;
import com.eastfair.pay.dto.JYCancelInvoiceDTO;
import com.eastfair.pay.dto.JYPaymentDTO;
import com.eastfair.pay.dto.PaymentDTO;
import com.eastfair.pay.entity.ApplyRefund;
import com.eastfair.pay.entity.CollectRecord;
import com.eastfair.pay.entity.InvoiceApplyer;
import com.eastfair.pay.entity.PaymentRecord;
import com.eastfair.pay.entity.TransactionOrder;
import com.eastfair.pay.enumeration.TransactionOrderOrderTypeEnum;
import com.eastfair.pay.enums.TransactionOrderStatusEnum;
import com.eastfair.pay.service.DictService;
import com.eastfair.pay.service.JyService;
import io.seata.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author Du Xiaobo
 * @date 2023/4/21 10:54
 */
@Slf4j
@Service
public class JyServiceImpl implements JyService {

    @Value("${mice-pay.transactionOrder.ruleId}")
    private String orderRuleId;

    @Resource
    private DictService dictService;

    @Value("${mice-pay.invoice.ruleId}")
    private String applyInvoiceRuleId;

    @Value("${mice-pay.uninvoice.ruleId}")
    private String cancelInvoiceRuleId;

    @Value("${mice-pay.refund.ruleId}")
    private String refundRuleId;

    @Value("${mice-pay.collect.ruleId}")
    private String collectRuleId;

    @Value("${mice-pay.uncollect.ruleId}")
    private String cancelCollectRuleId;

    @Value("${mice-pay.payment.ruleId}")
    private String paymentRuleId;


    @Override
    public JYReq<JYTransactionOrderDTO> buildAddTransactionOrderToJy(TransactionOrder transactionOrder) {
        JYReq<JYTransactionOrderDTO> jyReqestDTO = new JYReq();
        jyReqestDTO.setRuleId(orderRuleId);
        List<JYTransactionOrderDTO> orderDTOList = new ArrayList<>();
        JYTransactionOrderDTO orderDTO = new JYTransactionOrderDTO();
        orderDTO.setState(TransactionOrderStatusEnum.USE.getCode());
        orderDTO.setFkqs(transactionOrder.getPaymentPeriods());
        orderDTO.setGsjc(transactionOrder.getPayee());
        orderDTO.setGlzh(transactionOrder.getExhibitionName());
        orderDTO.setHtmc(transactionOrder.getOrderName());
        orderDTO.setHth(transactionOrder.getOrderNum());
        orderDTO.setHtzje(transactionOrder.getOrderAmount());
        orderDTO.setKhmc(transactionOrder.getPayer());
        orderDTO.setOptdate(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(transactionOrder.getOrderTime()));
        if (StringUtils.isNotBlank(transactionOrder.getPaymentPlan())) {
            List<OrderPaymentPlan> paymentPlans = JSON.parseArray(transactionOrder.getPaymentPlan(), OrderPaymentPlan.class);
            orderDTO.setMxdata(paymentPlans);
        }
        if (TransactionOrderOrderTypeEnum.BOND.eq(transactionOrder.getOrderType())) {
            orderDTO.setType(TransactionOrderOrderTypeEnum.BOND.getCode());
        } else if (TransactionOrderOrderTypeEnum.FINE.eq(transactionOrder.getOrderType())) {
            orderDTO.setType(TransactionOrderOrderTypeEnum.FINE.getCode());
        } else {
            orderDTO.setType("ORDINARY");
        }
        orderDTOList.add(orderDTO);
        jyReqestDTO.setParameter(orderDTOList);
        return jyReqestDTO;
    }

    @Override
    public JYReq<JYTransactionOrderDTO> buildUpdateTransactionOrderToJy(TransactionOrder transactionOrder) {
        JYReq<JYTransactionOrderDTO> jyReqestDTO = new JYReq();
        jyReqestDTO.setRuleId(orderRuleId);
        List<JYTransactionOrderDTO> orderDTOList = new ArrayList<>();
        JYTransactionOrderDTO orderDTO = new JYTransactionOrderDTO();
        // 修改
        // 订单状态
        orderDTO.setState(TransactionOrderStatusEnum.UPDATE.getCode());
        // 交易流水号
        orderDTO.setMainno(transactionOrder.getMainno());
        orderDTO.setFkqs(transactionOrder.getPaymentPeriods());
        orderDTO.setGsjc(transactionOrder.getPayee());
        orderDTO.setGlzh(transactionOrder.getExhibitionName());
        orderDTO.setHtmc(transactionOrder.getOrderName());
        orderDTO.setHth(transactionOrder.getOrderNum());
        orderDTO.setHtzje(transactionOrder.getOrderAmount());
        orderDTO.setKhmc(transactionOrder.getPayer());
        orderDTO.setOptdate(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(transactionOrder.getOrderTime()));
        if (StringUtils.isNotBlank(transactionOrder.getPaymentPlan())) {
            List<OrderPaymentPlan> paymentPlans = JSON.parseArray(transactionOrder.getPaymentPlan(), OrderPaymentPlan.class);
            orderDTO.setMxdata(paymentPlans);
        }
        if (TransactionOrderOrderTypeEnum.BOND.eq(transactionOrder.getOrderType())) {
            orderDTO.setType(TransactionOrderOrderTypeEnum.BOND.getCode());
        } else if (TransactionOrderOrderTypeEnum.FINE.eq(transactionOrder.getOrderType())) {
            orderDTO.setType(TransactionOrderOrderTypeEnum.FINE.getCode());
        } else {
            orderDTO.setType("ORDINARY");
        }
        orderDTOList.add(orderDTO);
        jyReqestDTO.setParameter(orderDTOList);
        return jyReqestDTO;
    }

    @Override
    public JYReq<JYTransactionOrderDTO> buildCancelTransactionOrderToJy(TransactionOrder transactionOrder) {
        JYReq<JYTransactionOrderDTO> jyReqestDTO = new JYReq();
        jyReqestDTO.setRuleId(orderRuleId);
        List<JYTransactionOrderDTO> orderDTOList = new ArrayList<>();
        JYTransactionOrderDTO orderDTO = new JYTransactionOrderDTO();
        // 取消
        if (StringUtils.isEmpty(transactionOrder.getMainno())) {
            log.info("交易流水号不存在,orderNum={}", transactionOrder.getOrderNum());
            throw new BizException(3021, "交易流水号不存在,订单号={}", transactionOrder.getOrderNum());
        }
        // 订单状态
        orderDTO.setState(TransactionOrderStatusEnum.CANCEL.getCode());
        // 交易流水号
        orderDTO.setMainno(transactionOrder.getMainno());
        orderDTOList.add(orderDTO);
        jyReqestDTO.setParameter(orderDTOList);
        return jyReqestDTO;
    }

    @Override
    public JYReq<JYApplyInvoiceInfoDTO> buildApplyInvoiceToJy(InvoiceApplyer invoiceApplyer) {
        JYReq<JYApplyInvoiceInfoDTO> applyInvoiceDTO = new JYReq();
        Map<String, String> invoiceTypeDict = dictService.getDictByType("INVOICE_TYPE");
        applyInvoiceDTO.setRuleId(applyInvoiceRuleId);
        List<JYApplyInvoiceInfoDTO> infoDTOS = new ArrayList<>();
        JYApplyInvoiceInfoDTO infoDTO = new JYApplyInvoiceInfoDTO();
        // 开票地址
        infoDTO.setAddress(invoiceApplyer.getToAddress());
        // 开票电话
        infoDTO.setTel(invoiceApplyer.getMobile());
        // 开票银行
        infoDTO.setBank(invoiceApplyer.getBankName());
        // 客户名称
        infoDTO.setKhmc(invoiceApplyer.getInvoiceTitle());
        // 纳税识别号
        infoDTO.setNssbh(invoiceApplyer.getInvoiceDutyParagraph());
        // 开票账户
        infoDTO.setZh(invoiceApplyer.getBankAccountNum());
        // 发票类型
        infoDTO.setFplbmc(invoiceTypeDict.get(invoiceApplyer.getInvoiceType()));
        // 开票公司
        infoDTO.setGsjc(invoiceApplyer.getInvoiceCompany());
        // 申请开票日期
        infoDTO.setSqrq(invoiceApplyer.getApplicationDate());
        // 开票明细
        List<JYApplyInvoiceMxDTO> mxDTOS = JSONObject.parseObject(invoiceApplyer.getDetails(), new TypeReference<List<JYApplyInvoiceMxDTO>>() {
        });
        infoDTO.setMxdata(mxDTOS);
        infoDTOS.add(infoDTO);
        applyInvoiceDTO.setParameter(infoDTOS);
        return applyInvoiceDTO;
    }

    @Override
    public JYReq<JYCancelInvoiceDTO> buildCancelInvoiceToJy(InvoiceApplyer invoiceApplyer) {
        JYReq<JYCancelInvoiceDTO> applyInvoiceDTO = new JYReq();
        applyInvoiceDTO.setRuleId(cancelInvoiceRuleId);
        List<JYCancelInvoiceDTO> infoDTOS = new ArrayList<>();
        JYCancelInvoiceDTO infoDTO = new JYCancelInvoiceDTO();
        // 开票公司
        infoDTO.setGsjc(invoiceApplyer.getInvoiceCompany());
        // 客户名称
        infoDTO.setKhmc(invoiceApplyer.getInvoiceTitle());
        // 开票流水号
        infoDTO.setMainno(invoiceApplyer.getMainno());
        infoDTOS.add(infoDTO);
        applyInvoiceDTO.setParameter(infoDTOS);
        return applyInvoiceDTO;
    }

    @Override
    public JYReq<JYApplyRefundDTO> buildRefundToJy(ApplyRefund applyRefund, TransactionOrder transactionOrder) {
        JYReq<JYApplyRefundDTO> req = new JYReq<>();
        req.setRuleId(refundRuleId);
        List<JYApplyRefundDTO> refundDTOS = new ArrayList<>();
        JYApplyRefundDTO refundDTO = new JYApplyRefundDTO();
        refundDTO.setGsjc(applyRefund.getMerchantName());
        refundDTO.setKhmc(applyRefund.getBankAccountName());
        refundDTO.setSqrq(applyRefund.getCreateTime());
        refundDTO.setYhmc(applyRefund.getBankName());
        refundDTO.setRemark(applyRefund.getRemart());
        refundDTO.setYhzh(applyRefund.getBankAccountNum());
        List<JYApplyRefundMxDTO> mxDTOS = new ArrayList<>();
        JYApplyRefundMxDTO mxDTO = new JYApplyRefundMxDTO();
        mxDTO.setHth(applyRefund.getBusinessNum());
        mxDTO.setYbje(applyRefund.getRefundAmount());
        mxDTO.setMainnofrom(transactionOrder.getMainno());
        mxDTOS.add(mxDTO);
        refundDTO.setMxdata(mxDTOS);
        refundDTOS.add(refundDTO);
        req.setParameter(refundDTOS);
        return req;
    }


    @Override
    public JYReq<JYPaymentCollectRecordDTO> buildCollectToJy(PaymentRecord paymentRecord, TransactionOrder transactionOrder, BigDecimal collectAmount) {
        JYReq<JYPaymentCollectRecordDTO> jyReqestDTO = new JYReq<>();
        jyReqestDTO.setRuleId(collectRuleId);
        List<JYPaymentCollectRecordDTO> recordDTOS = new ArrayList<>();
        JYPaymentCollectRecordDTO recordDTO = new JYPaymentCollectRecordDTO();
        recordDTO.setGsjc(paymentRecord.getCompanyName());
        recordDTO.setKhmc(paymentRecord.getBankAccountName());
        recordDTO.setZjllsh(paymentRecord.getMainno());
        recordDTO.setOptdate(paymentRecord.getPayTime());
        List<Collect> collectList = new ArrayList<>();
        Collect collect = new Collect();
        collect.setHth(transactionOrder.getOrderNum());
        collect.setYbje(collectAmount);
        collect.setMainnofrom(transactionOrder.getMainno());
        collect.setRemark("");
        collectList.add(collect);
        recordDTO.setMxdata(collectList);
        recordDTOS.add(recordDTO);
        jyReqestDTO.setParameter(recordDTOS);
        return jyReqestDTO;
    }

    @Override
    public JYReq<JYPaymentCollectRecordDTO> buildCancelCollectToJy(PaymentRecord paymentRecord, CollectRecord collectRecord) {
        JYReq<JYPaymentCollectRecordDTO> jyReqestDTO = new JYReq<>();
        jyReqestDTO.setRuleId(cancelCollectRuleId);
        List<JYPaymentCollectRecordDTO> recordDTOS = new ArrayList<>();
        JYPaymentCollectRecordDTO recordDTO = new JYPaymentCollectRecordDTO();
        recordDTO.setGsjc(paymentRecord.getCompanyName());
        recordDTO.setKhmc(paymentRecord.getBankAccountName());
        recordDTO.setMainno(collectRecord.getMainno());
        recordDTOS.add(recordDTO);
        jyReqestDTO.setParameter(recordDTOS);
        return jyReqestDTO;
    }

    @Override
    public JYReq<JYPaymentDTO> buildSuccessPaymentToJy(TransactionOrder transactionOrder, PaymentDTO payment) {
        JYReq<JYPaymentDTO> jyReqestDTO = new JYReq();
        jyReqestDTO.setRuleId(paymentRuleId);

        List<JYPaymentDTO> paymentList = new ArrayList<>();
        JYPaymentDTO paymentDTO = new JYPaymentDTO();

        paymentDTO.setGsjc(transactionOrder.getPayee());
        paymentDTO.setKhmc(transactionOrder.getPayer());
        paymentDTO.setHth(transactionOrder.getOrderNum());
        paymentDTO.setHtmc(transactionOrder.getOrderName());
        paymentDTO.setOptdate(DateTimeFormatter.ofPattern("yyyy-MM-dd").format(payment.getPaymentTime()));
        paymentDTO.setZdlsh(payment.getTransactionSerialNum());
        paymentDTO.setYbje(payment.getAmount());

        paymentList.add(paymentDTO);
        jyReqestDTO.setParameter(paymentList);

        return jyReqestDTO;
    }
}
